package com.course.file.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse;
import com.aliyuncs.vod.model.v20170321.GetMezzanineInfoResponse;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import com.course.file.config.AliyunVodConfig;
import com.course.file.util.VodUtils;
import com.course.server.common.Result;
import com.course.server.dto.FileDto;
import com.course.server.enums.FileUseEnum;
import com.course.server.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * @author: Durian
 * @date: 2021/5/23 10:51
 */
@Slf4j
@Service
public class VodService {

    @Resource
    private AliyunVodConfig aliyunVodConfig;
    @Resource
    private FileService fileService;

    @Transactional
    public FileDto upload(MultipartFile file, FileDto fileDto) throws Exception {
        String use = fileDto.getUse();
        String key = fileDto.getKey();
        String suffix = fileDto.getSuffix();

        // 保存文件到本地
        FileUseEnum useEnum = FileUseEnum.get(use);
        String dir = useEnum.name().toLowerCase();
        String path = dir + "/" + key + "." + suffix;

        String vod;
        String fileUrl;
        // 初始化VOD客户端并获取上传地址和凭证
        DefaultAcsClient vodClient = VodUtils.initVodClient(aliyunVodConfig.getAccessKeyId(), aliyunVodConfig.getAccessKeySecret());
        CreateUploadVideoResponse createUploadVideoResponse = VodUtils.createUploadVideo(vodClient, path);
        // 执行成功会返回VideoId、UploadAddress和UploadAuth
        vod = createUploadVideoResponse.getVideoId();
        JSONObject uploadAuth = JSONObject.parseObject(Base64.decodeBase64(createUploadVideoResponse.getUploadAuth()), JSONObject.class);
        JSONObject uploadAddress = JSONObject.parseObject(Base64.decodeBase64(createUploadVideoResponse.getUploadAddress()), JSONObject.class);
        // 使用UploadAuth和UploadAddress初始化OSS客户端
        log.debug("================初始化OssClient==========");
        OSSClient ossClient = VodUtils.initOssClient(uploadAuth, uploadAddress);
        log.debug("================初始化OssClient完成==========");
        // 上传文件，注意是同步上传会阻塞等待，耗时与文件大小和网络上行带宽有关
        VodUtils.uploadLocalFile(ossClient, uploadAddress, file.getInputStream());
        log.info("上传视频点播成功, vod : " + vod);
        GetMezzanineInfoResponse response = VodUtils.getMezzanineInfoResponse(vodClient, vod);
        log.info("获取视频信息: {}", JSON.toJSONString(response));
        fileUrl = response.getMezzanine().getFileURL();
        // 关闭OSSClient。
        ossClient.shutdown();

        log.debug("设置path和vod,保存文件记录到数据库");
        fileDto.setPath(path);
        fileDto.setVod(vod);
        fileService.save(fileDto);

        // 覆盖返回的path 用于临时访问，fileUrl会过期，不保存到db
        fileDto.setPath(fileUrl);
        return fileDto;
    }

    /**
     * 检查是  如果文件的key已经在file表存在，将file中的vod存入section
     * @param fileDto filedto
     * @return FileDto
     * @throws Exception Exception
     */
    public FileDto check(FileDto fileDto) throws Exception {
        FileDto dto = fileService.findByKey(fileDto.getKey());
        // file的vod有值表示文件存在视频点播中
        if (dto != null && StrUtil.isNotBlank(dto.getVod())) {
            DefaultAcsClient vodClient = VodUtils.initVodClient(aliyunVodConfig.getAccessKeyId(), aliyunVodConfig.getAccessKeySecret());
            GetMezzanineInfoResponse info = VodUtils.getMezzanineInfoResponse(vodClient, dto.getVod());
            log.info("获取视频信息, response : {}", JSON.toJSONString(info));
            dto.setPath(info.getMezzanine().getFileURL());
        }
        return dto;
    }

    public String getAuth(String vod) throws Exception {
        log.info("视频【{}】准备获取播放凭证", vod);
        DefaultAcsClient vodClient = VodUtils.initVodClient(aliyunVodConfig.getAccessKeyId(), aliyunVodConfig.getAccessKeySecret());
        GetVideoPlayAuthResponse videoPlayAuth = VodUtils.getVideoPlayAuth(vodClient, vod);
        log.debug("播放凭证：{}", videoPlayAuth.getPlayAuth());
        log.debug("视频元信息: {}", JSON.toJSONString(videoPlayAuth.getVideoMeta()));
        return videoPlayAuth.getPlayAuth();
    }
}
